/*
 * 作者：Peter Xiang
 * 联系方式：565067150@qq.com
 * 文档: https://github.com/PxGame
 * 创建时间: 2019/10/28 17:15:46
 */

using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using ActionSystem.Core;
using System.Reflection;
using System.Collections.Generic;

namespace XMLib.AM
{
    /// <summary>
    /// MenuView：配置，默认state类型，默认动画位置
    /// </summary>
    [Serializable]
    public class MenuView : IView
    {
        /// <summary>
        /// 不用确定配置
        /// </summary>
        public override bool checkConfig => false;
        public override string title => string.Empty;
        public override bool useAre => true;
        private string selectConfigName;

        protected override void OnGUI(Rect rect)
        {
            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal();
            //系统配置
            EditorGUI.BeginDisabledGroup(win.isRunning);
            SysEdit();
            EditorGUI.EndDisabledGroup();

            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("动作系统配置", GUILayout.Width(80));
            //将所有窗口的设置为非弹出
            if (GUILayout.Button("关闭弹出", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                foreach (var view in win.views)
                {
                    view.HidePopWindow();
                }
            }
            
            if (!win.isRunning)
            {
                //编辑器模式ui
                EditorMode();
            }
            else
            {
                //运行模式ui
                //PlayMode();
            }

            GUILayout.Space(5);
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
        }
        private void SysEdit()
        {
            Event evt = Event.current;
            EditorGUILayout.LabelField("系统全局配置", GUILayout.Width(80));

            EditorGUI.BeginChangeCheck();
            if (win.isSysConfigValid)
            {
                FieldInfo[] fields = typeof(ActionSystemConfig).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
                foreach (var field in fields)
                {
                    if (field.IsPublic || field.GetCustomAttribute<SerializeField>() != null)
                    {
                        EditorGUILayoutEx.DrawField(win.sysConfig, field);
                    }
                }

                //win.sysConfig = EditorGUILayoutEx.DrawObject<ActionSystemConfig>(GUIContent.none,win.sysConfig);
            }
            if (EditorGUI.EndChangeCheck()&&win.sysConfig!=null)
            {
                win.sysConfig.InitInternalData();
            }
            if (GUILayout.Button("保存", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //保存
                SaveSysConfig();
            }
            if (GUILayout.Button("保存到", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //保存到选择的文件中
                SaveSysConfigToSelect(win.sysConfig);
            }
            if (GUILayout.Button("还原修改", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //重新读取配置
                ResetSysConfig();
            }
            if (GUILayout.Button("拷贝配置", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //将当前配置的数据拷贝到内存中
                CopySysConfig();
            }
            if (GUILayout.Button("粘贴配置", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //将拷贝的配置，转为当前的配置
                PasteSysConfig();
            }
            GUILayout.FlexibleSpace();
            //配置文件
            if(win.UseAnimationClip)
            {
                EditorGUILayout.LabelField($"动画目录:{win.setting.aniamtionPath}");
                if (GUILayout.Button("更改", GUILayout.Width(40)))
                {
                    string path = EditorUtility.OpenFolderPanel("选择动画文件目录", Application.dataPath, " ");
                    int start = path.IndexOf("Assets/");
                    if (start != -1)
                    {
                        win.setting.aniamtionPath = path.Substring(start);
                        win.UpdateAnimationAssets();
                    }
                }
            }                      
            //配置文件
            EditorGUI.BeginChangeCheck();
            win.sysConfigAsset = (TextAsset)EditorGUILayout.ObjectField(win.sysConfigAsset, typeof(TextAsset), false);
            if (EditorGUI.EndChangeCheck())
            {
                if (win.sysConfigAsset != null)
                {
                    win.UpdateSysConfig(win.sysConfigAsset);
                }
            }
            //创建配置文件
            if (GUILayout.Button("创建", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                CreateNewSys();
            }
        }
        List<string> subclassNames = new List<string>();
        List<Type> subclass = new List<Type>();
        private void EditorMode()
        {
            Event evt = Event.current;
            
            if (GUILayout.Button("保存", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //保存
                SaveConfig();
            }
            if (GUILayout.Button("保存到", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //保存到选择的文件中
                SaveConfigToSelect(win.config);
            }
            if (GUILayout.Button("还原修改", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //重新读取配置
                ResetConfig();
            }
            if (GUILayout.Button("拷贝配置", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //将当前配置的数据拷贝到内存中
                CopyConfig();
            }
            if (GUILayout.Button("粘贴配置", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                //将拷贝的配置，转为当前的配置
                PasteConfig();
            }
            //需要显示的内容，枚举且具有flag属性
            win.setting.showView = EditorGUILayoutEx.DrawObject("显示", win.setting.showView);

            GUILayout.FlexibleSpace();

            EditorGUI.BeginChangeCheck();
            if(win.config != null)
            {
                bool isSubclass = win.config.defualtStateType.IsSubclassOf(typeof(BaseState));
                var res = UnityEditor.TypeCache.GetTypesDerivedFrom(typeof(BaseState));
                subclass.Clear();
                foreach(var t in res)
                {
                    if(!t.IsAbstract)
                    {
                        subclass.Add(t);
                    }
                }
                Type[] types = subclass.ToArray();
                if (!isSubclass|| win.config.defualtStateType.IsAbstract)
                {
                    //初始化
                    if (types.Length > 0)
                    {
                        win.config.defualtStateType = types[0];
                    }
                    else
                    {
                        win.config.defualtStateType = null;
                        Debug.LogError("请至少有1个继承BaseState的类");
                    }
                }
                if (win.config.defualtStateType != null)
                {
                    subclassNames.Clear();
                    int selectindex = 0;
                    for (int i = 0; i < types.Length; i++)
                    {
                        if (win.config.defualtStateType == types[i])
                        {
                            selectindex = i;
                            break;
                        }
                    }
                    for (int i = 0; i < types.Length; i++)
                    {
                        subclassNames.Add(types[i].ToString());
                    }
                    GUILayout.Label("默认状态类型:");
                    selectindex = EditorGUILayout.Popup(selectindex, subclassNames.ToArray(), GUILayout.MaxWidth(150));
                    win.config.defualtStateType = types[selectindex];
                }
            }            
            //选中obj
            win.actionMachineObj = (GameObject)EditorGUILayout.ObjectField(win.actionMachineObj, typeof(GameObject), true);
            if (EditorGUI.EndChangeCheck() && win.actionMachineObj != null)
            {
                if (win.actionMachineObj != null)
                {
                    win.UpdateTarget(win.actionMachineObj);
                }
            }
            //配置文件
            EditorGUI.BeginChangeCheck();
            win.configAsset = (TextAsset)EditorGUILayout.ObjectField(win.configAsset, typeof(TextAsset), false);
            if (EditorGUI.EndChangeCheck())
            {
                if (win.configAsset != null)
                {
                    win.UpdateConfig(win.configAsset);
                }
            }
            //创建配置文件
            if (GUILayout.Button("创建", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                CreateNew();
            }
        }

        private void PlayMode()
        {
            win.setting.showView = EditorGUILayoutEx.DrawObject("显示", win.setting.showView);
            GUILayout.FlexibleSpace();

            //string[] configNames = ActionMachineHelper.loadedConfig.Keys.ToArray();
            //if (configNames == null || configNames.Length == 0)
            //{
            //    selectConfigName = string.Empty;

            //    GUILayout.Label("当前没有已加载的配置文件");
            //    return;
            //}

            //bool isInit = true;
            //int index = 0;
            //if (!string.IsNullOrEmpty(selectConfigName))
            //{
            //    index = Array.FindIndex(configNames, t => string.Compare(t, selectConfigName) == 0);
            //    if (index < 0)
            //    {
            //        index = 0;
            //    }
            //}
            //else
            //{
            //    isInit = false;
            //}

            //GUILayout.Label("已加载配置文件");

            //EditorGUI.BeginChangeCheck();
            //index = EditorGUILayout.Popup(GUIContent.none, index, configNames, GUILayout.Width(200f));
            //if (EditorGUI.EndChangeCheck() || !isInit)
            //{
            //    selectConfigName = configNames[index];
            //    //装载配置
            //    MachineConfig config = ActionMachineHelper.loadedConfig[selectConfigName];
            //    win.config = config;
            //}

            if (GUILayout.Button("覆盖到", GUILayout.Width(80)))
            {
                GUI.FocusControl(null);
                SaveConfigToSelect(win.config);
            }
            if (GUILayout.Button("另存到", GUILayout.Width(100)))
            {
                GUI.FocusControl(null);
                CopyToNew(win.config);
            }
        }

        private void PasteConfig()
        {
            if (null == win.configAsset)
            {
                throw new RuntimeException($"未选择配置资源");
            }

            MachineConfig config = null;

            try
            {
                string data = EditorGUIUtility.systemCopyBuffer;
                config = DataUtility.FromJson(data) as MachineConfig;
                if (null == config)
                {
                    throw new Exception();
                }
            }
            catch (Exception)
            {
                Debug.LogWarning("剪贴板数据不匹配");
                return;
            }

            win.config = config;
        }
        private void PasteSysConfig()
        {
            if (null == win.sysConfigAsset)
            {
                throw new RuntimeException($"未选择系统配置资源");
            }

            ActionSystemConfig config = null;

            try
            {
                string data = EditorGUIUtility.systemCopyBuffer;
                config = DataUtility.FromJson(data) as ActionSystemConfig;
                if (null == config)
                {
                    throw new Exception();
                }
            }
            catch (Exception)
            {
                Debug.LogWarning("剪贴板数据不匹配");
                return;
            }

            win.sysConfig = config;
        }

        private void CopyConfig()
        {
            if (!win.isConfigValid)
            {
                throw new RuntimeException($"未选择配置资源");
            }

            string data = DataUtility.ToJson(win.config);
            EditorGUIUtility.systemCopyBuffer = data;
        }
        private void CopySysConfig()
        {
            if (!win.isConfigValid)
            {
                throw new RuntimeException($"未选择配置资源");
            }

            string data = DataUtility.ToJson(win.sysConfig);
            EditorGUIUtility.systemCopyBuffer = data;
        }

        private void ResetConfig()
        {
            win.UpdateConfig(win.configAsset);
        }
        private void ResetSysConfig()
        {
            win.UpdateSysConfig(win.sysConfigAsset);
        }

        public void SaveConfig()
        {
            if (!win.isConfigValid)
            {
                throw new RuntimeException($"未选择配置资源");
            }

            string path = AssetDatabase.GetAssetPath(win.configAsset);
            string data = DataUtility.ToJson(win.config);
            //数据保存
            File.WriteAllText(path, data);
            Debug.Log($"当前配置已保存 : {path}");
            AssetDatabase.Refresh();
        }
        public void SaveSysConfig()
        {
            if (!win.isSysConfigValid)
            {
                throw new RuntimeException($"未选择系统配置资源");
            }

            string path = AssetDatabase.GetAssetPath(win.sysConfigAsset);
            string data = DataUtility.ToJson(win.sysConfig);
            //数据保存
            File.WriteAllText(path, data);            
            Debug.Log($"当前配置已保存 : {path}");
            AssetDatabase.Refresh();
        }

        private void CreateNew()
        {
            //获取选中的文件夹
            string dir = EditorUtilityEx.GetSelectDirectory();
            //检测文件路径是否合法
            string filePath = EditorUtilityEx.ValidFilePath(Path.Combine(dir, "MachineConfig.bytes"));
            //创建空文件
            string data = DataUtility.ToJson(new MachineConfig());
            File.WriteAllText(filePath, data);
            Debug.Log($"配置已创建到 : {filePath}");
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
            win.configAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
            win.UpdateConfig(win.configAsset);
        }
        private void CreateNewSys()
        {
            //获取选中的文件夹
            string dir = EditorUtilityEx.GetSelectDirectory();
            //检测文件路径是否合法
            string filePath = EditorUtilityEx.ValidFilePath(Path.Combine(dir, "ActionSystemConfig.bytes"));
            //创建空文件
            string data = DataUtility.ToJson(new ActionSystemConfig());
            File.WriteAllText(filePath, data);
            Debug.Log($"系统配置已创建到 : {filePath}");
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
            win.sysConfigAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
            win.UpdateSysConfig(win.sysConfigAsset);
        }
        private void CopyToNew(MachineConfig config)
        {
            string dir = EditorUtilityEx.GetSelectDirectory();
            string filePath = EditorUtilityEx.ValidFilePath(Path.Combine(dir, "MachineConfig.bytes"));
            string data = DataUtility.ToJson(config);
            File.WriteAllText(filePath, data);
            AssetDatabase.Refresh();

            Debug.Log($"配置已拷贝到 : {filePath}");
        }

        private void SaveConfigToSelect(MachineConfig config)
        {
            //拿到当前工程视图中选中的配置文件
            string filePath = EditorUtilityEx.GetSelectFile(".bytes");
            if (string.IsNullOrEmpty(filePath))
            {
                Debug.LogWarning("选择的文件无效，写入失败");
                return;
            }
            //弹窗
            if (!EditorUtility.DisplayDialog("提示", $"是否将当前配置覆盖到选择文件?\n{filePath}", "是", "否"))
            {
                return;
            }
            //写入
            string data = DataUtility.ToJson(config);
            File.WriteAllText(filePath, data);
            AssetDatabase.Refresh();

            Debug.Log($"配置已覆盖到 : {filePath}");
        }
        private void SaveSysConfigToSelect(ActionSystemConfig config)
        {
            //拿到当前工程视图中选中的配置文件
            string filePath = EditorUtilityEx.GetSelectFile(".bytes");
            if (string.IsNullOrEmpty(filePath))
            {
                Debug.LogWarning("选择的文件无效，写入失败");
                return;
            }
            //弹窗
            if (!EditorUtility.DisplayDialog("提示", $"是否将当前配置覆盖到选择文件?\n{filePath}", "是", "否"))
            {
                return;
            }
            //写入
            string data = DataUtility.ToJson(config);
            File.WriteAllText(filePath, data);
            AssetDatabase.Refresh();

            Debug.Log($"配置已覆盖到 : {filePath}");
        }
        public override void OnUpdate()
        {
        }
    }
}